終於要來到前面提過好幾次的 life cycle 環節了~!
如果想要把我們的 form object 設計得跟 active record 一樣好用,那這個環節一定是讀者您需要去思考的部分。
那,我們從 active record 開始思考,一個 model object 一定會經歷以下過程
建立 (
initialize
):
根據傳入參數來初始化物件,以進行後續的操作。
驗證 (
validation
)
驗證傳入參數是否符合規定,如果符合才進行後面的步驟
執行 (
update
,save
,perform
orexecute
or somethig...)
form object 的主要動作。
不論讀者您想要您的執行階段做什麼事,基於SOLID 原則,筆者都不建議在同個 active model class 同時存在多個執行方法,像是 execute
and revert
共存之類 .. 。
像是下單 place order
與下單失敗後的回溯 revert order
就應該把邏輯分別放在兩個 class 內。
這樣一來,我們就可以盡可能的保持可讀性與效能,並且可以很直覺的規劃 callbacks:
class PlaceOrder
include ActiveModel::Model
include ActiveModel::Attributes
include ActiveModel::Validations::Callbacks
define_model_callbacks :initialize
define_model_callbacks :execute
# 定義你想要的 callbacks
def initialize(params)
run_callbacks(:initialize) do # 使用 run_callbacks 以激活 before, around, after 的 callbacks
super # 引用 active model 原生的 initialize 功能
end
end
def execute
run_callbacks(:execute) do
# Do something
end
end
end
關於
ActiveModel::Validations::Callbacks
的用途,可以參考先前講過的這篇
關於自訂 callbacks 要怎麼使用,可以參考這篇
可是如果,我的 form object 想要作為抽象層供其他 class 繼承使用,但我已經在抽象層定義好了 run_callbacks
包覆的範圍,如果別的工程師建立 class 繼承自我做的抽象層 form object,且覆寫掉我的執行方法,就變成無法觸發 callbacks,或者 run_callbacks
包覆範圍不如預期,怎麼辦?
其實只要你夠 tricky,這些都不是問題,但我們下一篇還是來好好探討這問題...。